﻿using ProjectScheduling.daos;
using ProjectScheduling.models;
using System.Data;

namespace ProjectScheduling.CalendarControl
{
    public partial class MonthPager : UserControl
    {
        public static readonly MonthPager b = new();
        private DateTime _day = DateTime.Today;
        private readonly List<Panel> _panels = [];
        public Action<DateTime>? clickAction;
        private List<RestDay> restDays = [];
        public List<(DateTime time, Panel panel, string msg)> DayPanelList = [];
        /// <summary>
        /// 当前用户名称
        /// </summary>
        public string CurrentUserName { get; set; } = "";
        /// <summary>
        /// 当前月所有的用户信息
        /// </summary>
        public Action<List<string>>? allUserAction;
        /// <summary>
        /// 获取当前月份中的所有用户信息 对比，如果与上次不同，提交上级页面的回调函数
        /// </summary>
        private List<string> AllUsers { get; set; } = [];
        // 窗口改变大小的时候重新绘制线条
        private Action? drawLineAction;
        private (int length, int height, int line_height) LineSize = new(0, 0, 0);
        public DateTime CurrDay
        {
            get
            {
                return _day;
            }
            set
            {
                _day = value;
                ChangeFunc(value);
            }
        }

        private readonly ToolTip _toolTip = new();
        private static readonly string[] s = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];
        private readonly Panel rightPanel = new();
        public MonthPager()
        {
            InitializeComponent();

            #region 创建单元格Panel
            for (var i = 0; i < 42; i++)
            {
                var p = new Panel
                {
                    BackColor = Color.White,
                    Cursor = Cursors.Hand,
                    Parent = p_main
                };

                p.MouseHover += (o, e) =>
                {
                    p.BackColor = Color.LightGray;
                };
                p.MouseLeave += (o, e) =>
                {
                    p.BackColor = (p.Tag is DateTime time && time == CurrDay) ? Color.LightBlue : Color.White;
                };
                p.Click += (o, e) =>
                {
                    if (p.Tag is DateTime time)
                    {
                        CurrDay = time;
                        clickAction?.Invoke(time);
                        ShowCurrentMessage();
                    }
                };

                _panels.Add(p);
                p_main.Controls.Add(p);
                p.SendToBack();
            }

            p_main.Controls.Add(rightPanel);
            #endregion

        }
        #region 获取休息日
        public void GetRestDays()
        {
            restDays = RestDayDao.Base.FindAll(it => it.Day.Month == CurrDay.Month);
        }
        #endregion


        private void P_main_Paint(object sender, PaintEventArgs e)
        {
            var g = e.Graphics;
            var w = p_main.Width - 20;
            var h = p_main.Height - 20;
            var wper = w / 8;
            var hper = (h - 30) / 6;
            var pen = new Pen(Color.Black, 1);
            g.DrawRectangle(pen, new RectangleF(10, 10, w, h));
            // 画横线
            for (var i = 0; i < 6; i++)
            {
                g.DrawLine(pen, 10, 40 + hper * i, 10 + wper * 7, 40 + hper * i);
            }
            // 画竖线
            for (var i = 0; i < 8; i++)
            {
                g.DrawLine(pen, 10 + wper * i, 10, 10 + wper * i, h + 10);
            }
            // 写星期
            for (var i = 0; i < 7; i++)
            {
                g.DrawString(s[i], new Font("宋体", 10), new SolidBrush(Color.Black), new PointF((wper / 2) - 18 + (wper * i), 17));
            }
        }
        private void MonthPager_Resize(object sender, EventArgs e)
        {
            try
            {
                p_main.Invalidate();
                var wper = (p_main.Width - 20) / 8;
                var hper = (p_main.Height - 50) / 6;
                var i = 0;
                // 设置Panel位置
                for (var y = 0; y < 6; y++)
                {
                    for (var x = 0; x < 7; x++)
                    {
                        var curr = _panels[i++];
                        curr.Location = new Point(11 + x * wper, 41 + y * hper);
                        curr.Size = new Size(wper - 2, hper - 2);
                    }
                }
                rightPanel.Left = wper * 7 + 10 + 2;
                rightPanel.Top = 11;
                rightPanel.Width = wper + 1;
                rightPanel.Height = Height - 21;
                ShowCurrentMessage();
                drawLineAction?.Invoke();
            }
            catch (Exception)
            {

            }
        }
        // 设置日期显示
        public void ChangeFunc(DateTime today)
        {

            var first = DateTime.Parse(today.ToString("yyyy-MM-01"));
            var curr = first;
            var week = (int)first.DayOfWeek;
            GetRestDays();

            void setPanel(Panel panel, DateTime time)
            {
                var isrest = new Func<bool>(() =>
                {
                    var obj = restDays.Find(it => it.Day == time);
                    if (obj != null)
                    {
                        return obj.IsRest;
                    }
                    else
                    {
                        return new[] { DayOfWeek.Sunday, DayOfWeek.Saturday }.Contains(time.DayOfWeek);
                    }
                })();
                panel.BackColor = isrest ? Control.DefaultBackColor : time == CurrDay ? Color.LightBlue : Color.White;
                panel.Enabled = !isrest;
                panel.Controls.Clear();
                panel.Tag = time;
                var label = new Label
                {
                    Text = curr.ToString("dd") + (isrest ? " (休)" : ""),
                    Font = new Font("宋体", 12),
                    Location = new Point(10, 10),
                    AutoSize = true,
                    ForeColor = curr.Month == CurrDay.Month ? Color.Black : Color.Gray,
                    BackColor = Color.Transparent
                };
                label.MouseHover += (o, e) =>
                {
                    panel.BackColor = Color.LightGray;
                };
                panel.Controls.Add(label);
                _toolTip.SetToolTip(control: panel,
                                    caption: time.ToString("yyyy年MM月dd日"));
            }
            DayPanelList.Clear();

            for (var i = week; i < 42; i++)
            {
                setPanel(_panels[i], curr);
                DayPanelList.Add((curr, _panels[i], ""));
                curr = curr.AddDays(1);
            }
            curr = first.AddDays(-1);
            for (var i = week - 1; i >= 0; i--)
            {
                setPanel(_panels[i], curr);
                DayPanelList.Add((curr, _panels[i], ""));
                curr = curr.AddDays(-1);
            }
            DayPanelList = [.. DayPanelList.OrderBy(it => it.time)];

            Task.Run(() =>
            {
                var states = new List<Enum_ProjectState> { Enum_ProjectState.已排期, Enum_ProjectState.实施中, Enum_ProjectState.已完结 };
                var minTime = DayPanelList.Min(it => it.time);
                var maxTime = DayPanelList.Max(it => it.time);
                var lists = new List<List<Projects>>();
                var allProjects = ProjectDao.Base.FindAll(it =>
                    it.ToDate > minTime &&
                    it.FromDate < maxTime &&
                    states.Contains(it.State) &&
                    (string.IsNullOrEmpty(CurrentUserName) || (it.StaffsList.Any(u => u.UserName == CurrentUserName)))
                ).OrderBy(it => it.FromDate).
                ToList();
                var users = ProjectDao.Base.ToTable("SELECT DISTINCT a.UserName FROM ProjectStaff a INNER JOIN Projects b ON a.ProjectId=b.Id WHERE b.FromDate<@maxTime AND b.ToDate>@minTime", ("@minTime", minTime), ("@maxTime", maxTime));
                var usernames = users.Rows.Cast<DataRow>().Select(it => it[0].ToString() ?? "").ToList();
                allUserAction?.Invoke(usernames);
                
                allProjects.ForEach(item =>
                {
                    var isIn = false;
                    foreach (var it in lists)
                    {
                        if (item.FromDate > it.Max(it => it.ToDate))
                        {
                            it.Add(item);
                            isIn = true;
                            break;
                        }
                    }
                    if (!isIn)
                    {
                        lists.Add([item]);
                    }
                });
                void writeLine(Color color, Projects project, int index)
                {
                    if (DayPanelList.Count == 0) return;
                    var startTime = project.FromDate < minTime ? minTime : project.FromDate;
                    var endTime = project.ToDate > maxTime ? maxTime : project.ToDate;
                    var noDatas = string.IsNullOrEmpty(project.RestDate) ? [] : (project.RestDate?.Split('、').Select(it => DateTime.Parse(it.ToString())).ToList().ToList() ?? []);
                    for (; startTime <= endTime; startTime = startTime.AddDays(1))
                    {
                        var start = DateTime.Parse(startTime.ToString("yyyy-MM-dd"));
                        var end = startTime;
                        if (noDatas.Contains(start))
                        {
                            start = start.AddDays(1);
                            continue;
                        }
                        var isIn = false;
                        for (; end <= endTime; end = end.AddDays(1))
                        {

                            var ed1 = DateTime.Parse(end.ToString("yyyy-MM-dd"));
                            var ed2 = ed1.AddDays(1);
                            var (time, panel, msg) = DayPanelList.Find(it => it.time == ed1);

                            var nxt = DayPanelList.Find(it => it.time == ed2 && ed1.AddDays(1) <= endTime);
                            if (nxt.panel == null)
                            {
                                isIn = true;
                                end = endTime;
                                break;
                            }
                            if (panel.Top != nxt.panel.Top)
                            {
                                isIn = true;
                                end = time;
                                break;
                            }
                        }
                        if (end == startTime && !isIn)
                        {
                            end = endTime;
                        }
                        startTime = end;
                        var ed = DateTime.Parse(end.ToString("yyyy-MM-dd"));
                        var st = DateTime.Parse(start.ToString("yyyy-MM-dd"));
                        var startObj = DayPanelList.Find(it => it.time == st).panel;
                        var endObj = DayPanelList.Find(it => it.time == ed).panel;
                        if (startObj == null || endObj == null) return;
                        var startLeft = startObj.Left;
                        var endRight = endObj.Right;
                        var startTop = startObj.Top;
                        void func()
                        {


                            var panelNew = new Button
                            {
                                Location = new Point(startLeft, startTop + index * LineSize.height + 30),
                                Size = new Size(endRight - startLeft, LineSize.line_height),
                                BackColor = color,
                                Parent = p_main,
                                Tag = "待清理",

                            };
                            panelNew.Click += (obj, e) => ViewProjectForm.b.Init(project.Id);
                            p_main.Controls.Add(panelNew);
                            panelNew.BringToFront();
                            var title = $"项目标题：{project.Name}\r\n开始时间：{project.FromDate:MM-dd}\r\n结束时间：{project.ToDate:MM-dd}\r\n工作人员：{string.Join("、", project?.StaffsList?.Select(it => it.UserName) ?? [])}";
                            _toolTip.SetToolTip(control: panelNew,
                                    caption: title);
                        }
                        try
                        {
                            Invoke(func);
                        }
                        catch (Exception)
                        {
                            func();
                        }
                    }
                }
                var colors = new[] { Color.Red, Color.Blue, Color.Yellow, Color.Green, Color.DarkBlue };
                drawLineAction = () =>
                {
                    var h = (p_main.Height - 50) / 6 - 30;
                    // 删除设置的
                    var ps = p_main.Controls.Cast<Control>().Where(it => it is Button p && p.Tag != null && p.Tag.ToString() == "待清理").Cast<Button>().ToList();

                    foreach (var p in ps)
                    {
                        try
                        {
                            Invoke(() =>
                            {
                                p_main.Controls.Remove(p);
                            });
                        }
                        catch (Exception)
                        {
                            p_main.Controls.Remove(p);
                        }
                    }
                    if (h < 20) return;
                    var len = h / 30;
                    if (len == 0) len = 1;
                    LineSize = (len, h / len, h * 2 / len / 3);

                    var j = 0;
                    for (var i = 0; i < Math.Min(lists.Count, len); i++)
                    {
                        foreach (var it in lists[i])
                        {
                            writeLine(colors[j++ % 5], it, i);
                        }
                    }
                };
                drawLineAction?.Invoke();

            });

            ShowCurrentMessage();

        }

        // 显示当前日期信息
        private void ShowCurrentMessage()
        {
            rightPanel.Controls.Clear();
            var top = 10;
            var width = rightPanel.Width - 20;
            var panel = new Panel
            {
                Top = top,
                Left = 10,
                Width = width,
                Height = 40,
                BorderStyle = BorderStyle.FixedSingle,
                BackColor = Color.FromArgb(200, 255, 255, 255),
            };
            panel.Controls.Add(new Label
            {
                Size = new Size(panel.Width, panel.Height),
                Location = new Point(0, 0),
                AutoSize = false,
                Text = width > 205 ? CurrDay.ToString("yyyy年MM月dd日") :
                        width > 130 ? CurrDay.ToString("MM月dd日") :
                        width > 66 ? CurrDay.ToString("dd日") : CurrDay.ToString("dd"),
                TextAlign = ContentAlignment.MiddleCenter,
                Font = new Font("宋体", 20)
            });
            rightPanel.Controls.Add(panel);
        }

    }
}